
// Copyright (c) 2012, 2013 All Right Reserved, http://hpc.utp.edu.my
// Author: Nordin Zakaria nordinzakaria@gmail.com
// All rights reserved.

#include <stdlib.h>
#include <string>
#include <map>
#include <vector>
#include <iostream>
#include <fstream>
#include <sstream>
using namespace std;
#include "Random.h"

#ifndef JOB_CLASS
#define JOB_CLASS

class Job;
typedef void (*JobInitialize)(Job&);

//! this class represents a single Job entity.
class Job
	{
	protected:
	//! the identity number of the job.
	unsigned int id;

	//! Initialize method
	JobInitialize initM;

	//! array of properties
	vector<int> properties;

	//! the list of preceding jobs.
	vector<unsigned int> precedence;

	public:

	//! A default constructor that does nothing.
	Job(){}

	//! A constructor that initializes the id
	/*!
		\param id	the id of the job
	*/
	Job(unsigned int id) {
		this->id = id;
		}

	//! Copy constructor 
	/*!
		\param other	the worker object to copy from
	*/
	Job(const Job& other)
		{
		copy(other);
		}

	//! Copy from another object to this object
	/*!
		\param other	the worker object to copy from
	*/
	void copy(const Job &other);

	//! Clone the object 
	/*!
		\return  a pointer to the cloned object
	*/
	Job* clone() const {
	        return new Job(*this);
		}

	//! Assign another object to this object 
	Job& operator=(const Job& arg) {
                copy(arg);
                return *this;
                }

	//! set the value of a property
	/*!
		\param prop		the value
		\param index		the index
	*/
    	void set(unsigned int prop, unsigned int index)
	{
		properties[index] = prop;
	}

	//! set the value of a property
	/*!
		\param index		the index
		\return 		the value
	*/
    	unsigned int get(unsigned int index) const
	{
		return properties[index];
	}

	//! set the number of properties for this object
	/*!
		\param sz		the number of properties
	*/
	void properties_size(unsigned int sz) 
	{
		properties.resize(sz);
	}

	//! get the number of properties for this object
	/*!
		\return  the number of properties
	*/
	unsigned int properties_size() const
	{
		return properties.size();
	}


	//! A function for setting the id of the job.
	/*!
		\param id		the id of the job
	*/
	void setID(unsigned int id)
		{
		this->id = id;
		}

	//! A function for getting the id of the job.
	/*!
		\return the id
	*/
	unsigned int getID()
		{
		return id;
		}

	//! A function for adding a single preceding job
	void addPrecedence(unsigned int jobid)
		{
		precedence.push_back(jobid);
		}

	//! read job object from a file
	/*!
	    \param infile   the input file
	    \param ascii    flag true if input file is true
	*/
	void read(FILE *infile, bool ascii=false);

	//! read job object from a binary file
	/*!
	    \param infile   the input file
	*/
	void read(ifstream &infile);

	//! write job object to a binary file
	/*!
	    \param outfile   the output file
	*/
	void write(FILE *outfile);

	//! Overloaded operator for output to a stream
	friend ostream& operator<<(ostream& os, const Job& obj); 

	//! Overloaded operator for input from a stream
	friend istream& operator>>(istream& is, Job& job);
 
	//! set the method to be used for initialization
	/*!
	    \param op   the method
	*/
	JobInitialize set_init(JobInitialize op) {
        	return (initM=op);
        	}

	//! get the method to be used for initialization
	/*!
	    \return the method
	*/
	JobInitialize get_init() const {
        	return initM;
        	}

	//! calls the initialization method for this object
	void init() {
        	(*initM)(*this);
        	}
	};

#endif

